/*
 * reference as ngx_palloc
 */


#ifndef UGX_MEMPOOL_ALLOC_H_
#define UGX_MEMPOOL_ALLOC_H_

#include <stdio.h>

#define _align(size, boundary) (((size) + ((boundary) - 1)) & ~((boundary) - 1))

#if ( defined( __linux__ ) || defined( __gnu_linux__ ) )
#include <stdint.h>
//typedef uint64_t uintptr_t;
#endif

#define _align_ptr(p, a)                                                   \
    (unsigned char*) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))

/*
 * UGX_MAX_ALLOC_FROM_POOL should be (_pagesize - 1), i.e. 4095 on x86.
 * On Windows NT it decreases a number of locked pages in a kernel.
 */
#define UGX_MAX_ALLOC_FROM_POOL  (_pagesize - 1)
#define UGX_DEFAULT_POOL_SIZE    (16 * 1024)
#define UGX_ALIGNMENT (sizeof(unsigned long))
#define UGX_POOL_ALIGNMENT       (16)
#define UGX_MIN_POOL_SIZE                                        \
    _align((sizeof(_pool_t) + 2 * sizeof(_pool_large_t)), \
             UGX_POOL_ALIGNMENT)



#ifdef __cplusplus
extern "C" {
#endif

extern int _pagesize;

typedef void  ( *_pool_cleanup_pt )( void *data );
typedef void* ( *_alloc_pt )( size_t size );
typedef void  ( *_free_pt )( void* p );

typedef struct _pool_cleanup_s       _pool_cleanup_t;
typedef struct _pool_s               _pool_t;
typedef struct _pool_large_s         _pool_large_t;
typedef struct _str_s                _str_t;
typedef struct _pool_data_s          _pool_data_t;

struct _pool_cleanup_s
{
    _pool_cleanup_pt handler;
    void              *data;
    _pool_cleanup_t *next;
};

struct _pool_large_s
{
    _pool_large_t *next;
    void            *alloc;
};

struct _str_s
{
    size_t         len;
    unsigned char *data;
};

struct _pool_data_s
{
    unsigned char *last;
    unsigned char *end;
    _pool_t     *next;
    unsigned int   failed;
};


struct _pool_s
{
    _pool_data_t     d;
    unsigned int       max;//the max size of memory allocated from pool
    _pool_t         *current;
    _pool_large_t   *large;
    _pool_cleanup_t *cleanup;
};

/**
 * @param pool_size - the pool size
 * @param max_alloc_from_pool - the max memory unit alloc from pool
 */
_pool_t *_create_pool( size_t pool_size, size_t max_alloc_from_pool /*= UGX_MAX_ALLOC_FROM_POOL*/  );
void _destroy_pool( _pool_t *pool );
void _reset_pool( _pool_t *pool );

//malloc memory from _pool_t
void *_palloc( _pool_t *pool, size_t size );
void *_pnalloc( _pool_t *pool, size_t size );
void *_pcalloc( _pool_t *pool, size_t size );
void *_pmemalign( _pool_t *pool, size_t size, size_t alignment );
int   _pfree( _pool_t *pool, void *p );


_pool_cleanup_t *_pool_cleanup_add( _pool_t *p, size_t size );


void _set_alloc( _alloc_pt alloc_pt );
void _set_free( _free_pt free_pt );

int _dbgprint( const char* fmt, ... );

#ifdef __cplusplus
} // end of extern "C" {
#endif

#endif /* _UGX_PALLOC_H_INCLUDED_ */


